package org.groupg.practice.data._500wData;

import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.groupg.practice.data.DataRecord;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 针对500万数据量的高性能结构化存储
 * 相比传统List<Object>可减少60-80%内存
 */
public class HighVolumeDataStore {
    // 使用分离的原始类型数组存储，避免对象头开销
    private final IntArrayList ids;
    private final LongArrayList timestamps;
    private final DoubleArrayList values;
    private final ObjectArrayList<String> labels;

    // 用于快速查找的索引
    private final it.unimi.dsi.fastutil.ints.Int2ObjectMap<IntArrayList> labelIndex;

    public HighVolumeDataStore(int initialCapacity) {
        this.ids = new IntArrayList(initialCapacity);
        this.timestamps = new LongArrayList(initialCapacity);
        this.values = new DoubleArrayList(initialCapacity);
        this.labels = new ObjectArrayList<>(initialCapacity);
        this.labelIndex = new it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap<>();
    }

    /**
     * 添加数据 - 使用原始类型避免装箱
     */
    public void addRecord(int id, long timestamp, double value, String label) {
        int index = ids.size();
        ids.add(id);
        timestamps.add(timestamp);
        values.add(value);
        labels.add(label);

        // 构建标签索引
        int labelHash = label.hashCode();
        IntArrayList labelIndices = labelIndex.get(labelHash);
        if (labelIndices == null) {
            labelIndices = new IntArrayList();
            labelIndex.put(labelHash, labelIndices);
        }
        labelIndices.add(index);
    }

    /**
     * 批量添加 - 更高效
     */
    public void addBatch(int[] ids, long[] timestamps, double[] values, String[] labels) {
        for (int i = 0; i < ids.length; i++) {
            addRecord(ids[i], timestamps[i], values[i], labels[i]);
        }
    }

    /**
     * 获取记录 - 按需构造对象，避免全量对象存储
     */
    public DataRecord getRecord(int index) {
        if (index < 0 || index >= ids.size()) {
            return null;
        }
        return new DataRecord(
                ids.getInt(index),
                timestamps.getLong(index),
                values.getDouble(index),
                labels.get(index)
        );
    }

    /**
     * 根据标签快速查找 - 利用预构建的索引
     */
    public List<DataRecord> findByLabel(String label) {
        int labelHash = label.hashCode();
        IntArrayList indices = labelIndex.get(labelHash);
        if (indices == null) {
            return Collections.emptyList();
        }

        List<DataRecord> results = new ArrayList<>(indices.size());
        for (int i = 0; i < indices.size(); i++) {
            int index = indices.getInt(i);
            if (label.equals(labels.get(index))) {
                results.add(getRecord(index));
            }
        }
        return results;
    }

    /**
     * 范围查询 - 利用原始数组的高效遍历
     */
    public void processInRange(long startTime, long endTime, RecordProcessor processor) {
        for (int i = 0; i < timestamps.size(); i++) {
            long ts = timestamps.getLong(i);
            if (ts >= startTime && ts <= endTime) {
                processor.process(
                        ids.getInt(i),
                        ts,
                        values.getDouble(i),
                        labels.get(i)
                );
            }
        }
    }

    /**
     * 内存使用统计
     */
    public void printMemoryStats() {
        long estimatedSize =
                ids.size() * 4L +          // 每个int 4字节
                        timestamps.size() * 8L +   // 每个long 8字节
                        values.size() * 8L +       // 每个double 8字节
                        labels.size() * 32L;       // 估算每个String约32字节

        System.out.printf("数据条数: %,d%n", ids.size());
        System.out.printf("预估内存: %,d MB%n", estimatedSize / (1024 * 1024));
        System.out.printf("原始List<DataRecord>预估: %,d MB%n",
                (ids.size() * 100) / (1024 * 1024)); // 假设每个对象约100字节
    }

    // 处理器接口，避免创建临时对象
    public interface RecordProcessor {
        void process(int id, long timestamp, double value, String label);
    }


}